package com.youlu.campus.service.activity.impl;

import com.alibaba.fastjson.JSON;
import com.youlu.campus.common.exception.BusinessException;
import com.youlu.campus.component.SmsUtil;
import com.youlu.campus.entity.*;
import com.youlu.campus.entity.VO.req.CheckMobileVO;
import com.youlu.campus.entity.dto.sms.SmsBaseInfoDTO;
import com.youlu.campus.entity.enums.TaskBizType;
import com.youlu.campus.service.account.AccountMobileInfoService;
import com.youlu.campus.service.activity.*;
import com.youlu.campus.service.ca.GenerateUserCaService;
import com.youlu.campus.service.invite.UserInviteRecordService;
import com.youlu.campus.service.ranking.UserActivityPointRankingService;
import com.youlu.campus.service.ranking.entity.UserActivityPointRanking;
import com.youlu.campus.service.sms.SmsServerService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service
public class ActivityUserServiceImpl implements ActivityUserService {
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private ActivityUserAuthInfoService activityUserAuthInfoService;
    @Autowired
    private SmsUtil smsUtil;
    @Autowired
    private UserInviteRecordService userInviteRecordService;
    @Autowired
    private ActivityTaskService activityTaskService;
    @Autowired
    private UserActivityPointRankingService pointRankingService;
    @Autowired
    private AccountMobileInfoService accountMobileInfoService;
    @Autowired
    private ActivityService activityService;
    @Autowired
    private UserParticipateActivityInfoService upService;

    @Autowired
    private GenerateUserCaService generateUserCaService;

    @Autowired
    private SmsServerService smsServerService;

    @Override
    public boolean checkMobile(String userId, String activityId) {
        log.info(":>>> 开始检查用户:{} 活动:{} 是否验证手机号", userId, activityId);
        if (StringUtils.isBlank(userId) || StringUtils.isBlank(activityId)) {
            log.error("账号ID或活动ID为空");
            throw new BusinessException("账号ID或活动ID为空");
        }
        ActivityUserAuthInfo d = activityUserAuthInfoService.find(userId, activityId);
        if (Objects.isNull(d)) {
            return false;
        }
        return d.getCheckMobile();
    }

    @Override
    public boolean signUp(@NotNull CheckMobileVO req) {
        log.info(":>>> 用户报名活动:{}", JSON.toJSONString(req));
        Date date = new Date();
        final String userId = req.getUserPO().getId();
        if (Boolean.TRUE.equals(req.getNeedCheckMobile())) {
            SmsBaseInfoDTO dto = SmsBaseInfoDTO.builder().phone(req.getMobile()).code(req.getCode()).build();
            Pair<Boolean, String> re =  smsServerService.checkVerifyCode(dto);
            if (!re.getLeft()) {
                throw new BusinessException(re.getRight());
            }
            ActivityUserAuthInfo auth = activityUserAuthInfoService.find(userId, req.getActivityId());
            if (!Objects.nonNull(auth)) {
                auth = new ActivityUserAuthInfo();
                auth.setActivityId(req.getActivityId());
                auth.setCheckMobile(true);
                auth.setCheckMobileTime(date);
                auth.setMobile(req.getMobile());
                auth.setUserId(req.getUserPO().getId());
                activityUserAuthInfoService.craete(auth);
            }
            AccountMobileInfo accountMobileInfo = accountMobileInfoService.find(req.getMobile(), userId);
            if (Objects.isNull(accountMobileInfo)) {
                accountMobileInfo = new AccountMobileInfo();
                accountMobileInfo.setUserId(userId);
                accountMobileInfo.setMobile(req.getMobile());
                accountMobileInfo.setIp(req.getClientIp());
                accountMobileInfo.setCheckTime(date);
                accountMobileInfoService.create(accountMobileInfo);
            }

        }
        Query query = new Query().addCriteria(Criteria.where("userId").is(userId).and("activityId").
                is(req.getActivityId()));
        List<UserParticipateActivityInfo> ups = mongoTemplate.find(query, UserParticipateActivityInfo.class);
        if (CollectionUtils.isEmpty(ups)) {
            UserParticipateActivityInfo up = new UserParticipateActivityInfo();
            up.setUserId(userId);
            up.setActivityId(req.getActivityId());
            up.setJoined(true);
            up.setSignUpTime(date);
            up.setCreatedTime(date);
            up.setMobile(req.getMobile());
            mongoTemplate.insert(up);
            // 需要更新排行榜、邀请记录
            this.afterSignUpUpdate(req.getUserPO(), req.getActivityId(), req.getPaltform());
            accountMobileInfoService.updateAccountMobile(req.getUserPO().getId(), req.getMobile(), req.getPaltform());
            upService.increJoinedCount(req.getActivityId(), 1L);
            activityService.updateActivityJoinNum(req.getActivityId(),1,new Date());
            return true;
        }
        boolean joined = this.signUped(ups);
        if (joined) {
            return true;
        }
        Update update = new Update();
        update.set("joined", true);
        update.set("signUpTime", date);
        mongoTemplate.updateMulti(query, update, UserParticipateActivityInfo.class);
        // 需要更新排行榜、邀请记录
        this.afterSignUpUpdate(req.getUserPO(), req.getActivityId(), req.getPaltform());
        accountMobileInfoService.updateAccountMobile(req.getUserPO().getId(), req.getMobile(), req.getPaltform());
        upService.increJoinedCount(req.getActivityId(), 1L);
        activityService.updateActivityJoinNum(req.getActivityId(),1,new Date());
        return true;
    }

    @Override
    public void afterSignUpUpdate(UserPO userPO, String activityId, String platform) {
        log.error(":>>> 开始处理用户:{} 活动:{} 报名完成后其他信息更新", JSON.toJSONString(userPO), activityId);
        if (Objects.isNull(userPO) || StringUtils.isBlank(activityId)) {
            log.error(":>>> 用户信息或活动ID为空");
            return;
        }
        ActivityTaskInfo taskInfo = activityTaskService.find(activityId, TaskBizType.INVITE);
        if (Objects.isNull(taskInfo)) {
            log.error(":>>> 活动:{} 邀请任务不存在", activityId);
            return;
        }
        UserInviteRecord record = userInviteRecordService.getByInvitedToUserId(userPO.getId(), activityId, taskInfo.getId());
        if (Objects.isNull(record)) {
            log.error(":>>> 活动:{} 用户:{} 没有被邀请记录", activityId, userPO.getId());
            return;
        }
        boolean re = userInviteRecordService.updateUserInviteStatus(record.getId());
        log.info(":>>> 更新邀请记录:{} 结果为:{}", record.getId(), re);
        if (!re) {
            return;
        }
        Double quantity=0D;
        Query query = new Query().addCriteria(Criteria.where("id").is(record.getInvitedByUserId()));
        UserPO invitedBy = mongoTemplate.findOne(query, UserPO.class);
        UserActivityPointRanking userActivityPointRanking = pointRankingService.find(invitedBy.getId(), "", activityId);
        if(Objects.nonNull(userActivityPointRanking)){
            quantity = userActivityPointRanking.getQuantity();
        }
        pointRankingService.updatePoint(invitedBy, activityId, taskInfo.getPoints().intValue());
        generateUserCaService.generateUserCa(activityId,quantity.intValue()+taskInfo.getPoints().intValue(),invitedBy);
        //ActivityInfo activityInfo = activityService.findOne(activityId);
        //activityService.generateUserCa(activityId, activityInfo.getId(), invitedBy, platform);
    }

    /**
     * 判断用户是否报名
     *
     * @param ups
     * @return
     */
    protected boolean signUped(List<UserParticipateActivityInfo> ups) {
        if (CollectionUtils.isEmpty(ups)) {
            return false;
        }
        for (UserParticipateActivityInfo up : ups) {
            if (Boolean.TRUE.equals(up.getJoined())) {
                return true;
            }
        }
        return false;
    }
}
